﻿using System;
using System.Threading;

namespace ThreadText
{
    class LockOne
    {
        private int i = 0;
        public void FirstThread()
        {
            Thread one = new Thread(ThreadOne);
            Thread two = new Thread(ThreadTwo);
            one.Start();
            two.Start();
            Three();//主线程先走
            //Console.ReadLine();
        }
        private void ThreadOne()
        {
            lock (this)
            {
                Console.WriteLine(i);
                Console.WriteLine("First");
                Thread.Sleep(1000);
                Console.WriteLine(i);//this中的属性依然能够被别的线程改变. i = 1。当在另一个线程中的方法中对变量进行改变，而该方法没有lock，就会改变本线程中的变量
                Console.WriteLine("ThreadOne");
            }
        }
        private void ThreadTwo()
        {
            Thread.Sleep(500);
            this.i = 1;
            Console.WriteLine(i);
            Console.WriteLine("Change the value in locking");

        }
        private void Three()
        {
            this.i = 3;
            Console.WriteLine("Three");
        }
    }

    class LockTwo
    {
        private int i = 0;
        public void SecondThread()
        {
            Thread one = new Thread(ThreadOne);
            Thread two = new Thread(ThreadTwo);
            one.Start();
            two.Start();
        }
        private void ThreadOne()
        {
            lock (this)
            {
                Console.WriteLine(i);
                Console.WriteLine("Second");
                Thread.Sleep(1000);
                Console.WriteLine(i);
                Console.WriteLine("SecondThreadOne");
            }
        }
        private void ThreadTwo()
        {
            Console.WriteLine("进来ThreadTwo，但必须等ThreadOne的lock结束才运行下面的代码lock");
            //ThreadTwo中的lock需要等到ThreadOne种lock释放后才开始运行,释放之前一直处于等待状态,这就是标志的表现
            lock (this)
            {
                Thread.Sleep(500);
                this.i = 1;//这里的i已经被ThreadOne给锁住了，必须=ThreadOne结束后才能运行ThreadTwo的lock。
                Console.WriteLine("现在才开始进入lock");
                Console.WriteLine(i); 
                Console.WriteLine("Can't change the value in locking");
            }
        }
        //对于任何一个对象来说,他在内存中的第一部分放置的是所有方法的地址,第二部分放着一个索引,他指向CLR中的SyncBlock Cache区域中的一个SyncBlock.
        //就是说,当你执行Monitor.Enter（Object）时，如果object的索引值为负数，就从SyncBlock Cache中选区一个SyncBlock，将其地址放在object的索引中。
        //这样就完成了以object为标志的锁定，其他的线程想再次进行Monitor.Enter(object)操作，将获得object为正数的索引，然后就等待。
        //直到索引变为负数，即线程使用Monitor.Exit（object)将索引变为负数。
        //lock后括号里面的值不是说把整个对象锁住,而是对他的一个值进行了修改,使别的lock不能锁住他,这才是lock(object)的真面目.
    }
}
